package cn.bertsir.zbar.utils;


import cn.bertsir.zbar.Qr.*;
import cn.bertsir.zbar.decoding.DecodeFormatManager;
import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.render.Texture;
import ohos.agp.utils.*;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.data.rdb.ValuesBucket;
import ohos.global.configuration.Configuration;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import ohos.media.photokit.metadata.AVStorage;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;
import ohos.utils.net.Uri;
import ohos.vibrator.agent.VibratorAgent;
import ohos.vibrator.bean.VibrationPattern;

import java.io.*;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

/**
 * Created by Bert on 2017/9/20.
 */

public class QRUtils {

    private static QRUtils instance;
    private PixelMap scanBitmap;
    private Context mContext;


    public static QRUtils getInstance() {
        if (instance == null) {
            instance = new QRUtils();
        }
        return instance;
    }

    //    /**
//     * 获取RGBLuminanceSource
//     * @param bitmap
//     * @return
//     */
    private static RGBLuminanceSource getRGBLuminanceSource(PixelMap bitmap) {
        int width = bitmap.getImageInfo().size.width;
        int height = bitmap.getImageInfo().size.height;

        int[] pixels = new int[width * height];
        bitmap.readPixels(pixels, 0, width, new Rect(0, 0, width, height));
        return new RGBLuminanceSource(width, height, pixels);

    }
    private static RGBLuminanceSource getRGBLuminanceSource(PixelMap bitmap,Rect rect) {
        int width = bitmap.getImageInfo().size.width;
        int height = bitmap.getImageInfo().size.height;

        int[] pixels = new int[rect.width * rect.height];
        bitmap.readPixels(pixels, 0, rect.width, rect);
        return new RGBLuminanceSource(rect.width, rect.height, pixels);

    }
    /**
     * 将map解析
     *
     * @param map map
     * @return 字符串信息
     */
    public static String parseInfoFromBitmap(PixelMap map) {
        Result result1 = null;
        MultiFormatReader multiFormatReader = new MultiFormatReader();
        multiFormatReader.setHints(DecodeFormatManager.ALL_HINTS);
        RGBLuminanceSource rgbLuminanceSource = getRGBLuminanceSource(map);
        try {
            result1 = multiFormatReader.decodeWithState(new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource)));
            if (result1 == null) {
                //如果没有解析成功，再采用GlobalHistogramBinarizer解析一次
                result1 = multiFormatReader.decodeWithState(new BinaryBitmap(new GlobalHistogramBinarizer(rgbLuminanceSource)));
            }
            System.out.println("===parseInfoFromBitmap====" + result1.getText());
            return result1.getText();
        } catch (Exception e) {
            System.out.println("===NotFoundException====" + e.getMessage());
        }
        return null;
//        // 解码的参数
//        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(3);
//        // 可以解析的编码类型
//        Vector<BarcodeFormat> decodeFormats = new Vector<BarcodeFormat>();
//        if (decodeFormats.isEmpty()) {
//            decodeFormats = new Vector<BarcodeFormat>();
//            // 这里设置可扫描的类型，我这里选择了都支持
//            decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
//            decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
//            decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
//        }
//        hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
//        // 设置继续的字符编码格式为UTF8
//        hints.put(DecodeHintType.CHARACTER_SET, "UTF8");
//        // 设置解析配置参数
//        multiFormatReader.setHints(hints);
//        try {
//            BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BitmapLuminanceSource(map)));
//            Result rawResult = multiFormatReader.decodeWithState(binaryBitmap);
//            if (rawResult != null) {
//                result = rawResult.getText();
//            }
//        } catch (Exception ignored) {
//            Log.error(ignored.getMessage());
//        }
//        return result;
    }

    /**
     * 识别本地二维码
     *
     * @param path 本地路径
     * @return String
     * @throws Exception Exception
     */
    public String decodeQRcode(String path) throws Exception {
        //对图片进行灰度处理，为了兼容彩色二维码
        PixelMap qrbmp = compressImage(path);
        qrbmp = toGrayscale(qrbmp);
        if (qrbmp != null) {
            return decodeQRcode(qrbmp);
        } else {
            return "";
        }
    }

    public String decodeQRcode(ohos.agp.components.Image iv) {
        PixelMap qrbmp = iv.getPixelMap();
        if (qrbmp != null) {
            return decodeQRcodeByZxing(qrbmp);
        } else {
            return "";
        }
    }


    /**
     * 扫描二维码图片的方法
     *
     * @param path 图片路径
     * @return String
     */
    public String decodeQRcodeByZxing(String path) {
        if (TextTool.isNullOrEmpty(path)) {
            return null;

        }
        Hashtable<DecodeHintType, String> hints = new Hashtable();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码
        PixelMap scanBitmap = compressImage(path);
        int[] data = new int[scanBitmap.getImageInfo().size.width * scanBitmap.getImageInfo().size.height];
        scanBitmap.readPixels(data, 0, scanBitmap.getImageInfo().size.width, new Rect(0, 0, scanBitmap.getImageInfo().size.width, scanBitmap.getImageInfo().size.height));
        RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getImageInfo().size.width, scanBitmap.getImageInfo().size.height, data);
        BinaryBitmap binaryBitmap = new BinaryBitmap(new GlobalHistogramBinarizer(rgbLuminanceSource));
        QRCodeReader reader = new QRCodeReader();
        Result result = null;
        try {
            result = reader.decode(binaryBitmap, hints);
        } catch (NotFoundException e) {

        } catch (ChecksumException e) {

        } catch (FormatException e) {

        }
        if (result == null) {
            return "";
        } else {
            return result.getText();
        }
    }

    /**
     * 扫描二维码图片的方法
     *
     * @param bitmap PixelMap
     * @return String
     */
    public String decodeQRcodeByZxing(PixelMap bitmap) {
        Hashtable<DecodeHintType, String> hints = new Hashtable();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码
        scanBitmap = bitmap;
        int[] data = new int[scanBitmap.getImageInfo().size.width * scanBitmap.getImageInfo().size.height];
        scanBitmap.readPixels(data, 0, scanBitmap.getImageInfo().size.width, new Rect(0, 0, scanBitmap.getImageInfo().size.width, scanBitmap.getImageInfo().size.height));
        RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getImageInfo().size.width, scanBitmap.getImageInfo().size.height, data);
        BinaryBitmap binaryBitmap = new BinaryBitmap(new GlobalHistogramBinarizer(rgbLuminanceSource));
        QRCodeReader reader = new QRCodeReader();
        Result result = null;
        try {
            result = reader.decode(binaryBitmap, hints);
        } catch (NotFoundException e) {
            System.out.println("=====decodeQRcodeByZxing======" + e.getMessage());
        } catch (ChecksumException e) {
            System.out.println("=====decodeQRcodeByZxing======" + e.getMessage());
        } catch (FormatException e) {
            System.out.println("=====decodeQRcodeByZxing======" + e.getMessage());
        }
        if (result == null) {
            return null;
        } else {
            return result.getText();
        }

    }

    public String decodeQRcode(PixelMap barcodeBmp){
        int width = barcodeBmp.getImageInfo().size.width;
        int height = barcodeBmp.getImageInfo().size.height;
        int[] pixels = new int[width * height];
        barcodeBmp.readPixels(pixels, 0, width, new Rect(0, 0, width, height));
        Image barcode = new Image(width, height, "RGB4");
        barcode.setData(pixels);
        ImageScanner reader = new ImageScanner();
        reader.setConfig(Symbol.NONE, Config.ENABLE, 0);
        reader.setConfig(Symbol.QRCODE, Config.ENABLE, 1);
        int result = reader.scanImage(barcode.convert("Y800"));
        String qrCodeString = null;
        if (result != 0) {
            SymbolSet syms = reader.getResults();
            for (Symbol sym : syms) {
                qrCodeString = sym.getData();
            }
        }
        barcodeBmp.release();
        return qrCodeString;
    }

    /**
     * 识别本地条形码
     *
     * @param path
     * @return String
     */
    public String decodeBarcode(String path)  {
        //对图片进行灰度处理，为了兼容彩色二维码
        PixelMap qrbmp = compressImage(path);
        qrbmp = toGrayscale(qrbmp);
        if (qrbmp != null) {
            return decodeBarcode(qrbmp);
        } else {
            return "";
        }

    }
    public String decodeBarcode(PixelMap barcodeBmp) {
        int width = barcodeBmp.getImageInfo().size.width;
        int height = barcodeBmp.getImageInfo().size.height;
        int[] pixels = new int[width * height];
        barcodeBmp.readPixels(pixels, 0, width, new Rect(0, 0, width, height));
        Image barcode = new Image(width, height, "RGB4");
        barcode.setData(pixels);
        ImageScanner reader = new ImageScanner();
        reader.setConfig(Symbol.NONE, Config.ENABLE, 0);
        reader.setConfig(Symbol.CODE128, Config.ENABLE, 1);
        reader.setConfig(Symbol.CODE39, Config.ENABLE, 1);
        reader.setConfig(Symbol.EAN13, Config.ENABLE, 1);
        reader.setConfig(Symbol.EAN8, Config.ENABLE, 1);
        reader.setConfig(Symbol.UPCA, Config.ENABLE, 1);
        reader.setConfig(Symbol.UPCE, Config.ENABLE, 1);
        int result = reader.scanImage(barcode.convert("Y800"));
        String qrCodeString = null;
        if (result != 0) {
            SymbolSet syms = reader.getResults();
            for (Symbol sym : syms) {
                qrCodeString = sym.getData();
            }
        }
        return qrCodeString;
    }
    /**
     * 生成二维码
     *
     * @param content 二维码信息
     * @return PixelMap
     */
    public PixelMap createQRCode(String content) {
        return createQRCode(content, 300, 300);
    }

    /**
     * 生成二维码
     *
     * @param content 二维码信息
     * @param width width
     * @param height height
     * @return PixelMap
     */
    public PixelMap createQRCode(String content, int width, int height) {
        PixelMap bitmap = null;
        BitMatrix result = null;
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        try {
            Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//这里调整二维码的容错率
            hints.put(EncodeHintType.MARGIN, 3);   //设置白边取值1-4，值越大白边越大
            result = multiFormatWriter.encode(new String(content.getBytes("UTF-8"), "ISO-8859-1"), BarcodeFormat
                    .QR_CODE, width, height, hints);
            int w = result.getWidth();
            int h = result.getHeight();
            int[] pixels = new int[w * h];
            for (int y = 0; y < h; y++) {
                int offset = y * w;
                for (int x = 0; x < w; x++) {
                    pixels[offset + x] = result.get(x, y) ? Color.BLACK.getValue() : Color.WHITE.getValue();
                }
            }
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            initializationOptions.size = new Size(w, h);
            initializationOptions.pixelFormat = PixelFormat.RGB_565;
            bitmap = PixelMap.create(pixels, 0, width, initializationOptions);
//            bitmap.writePixels(pixels, width, height, new Rect(0, 0, 0, 0));
        } catch (Exception e) {
            System.out.println("=============" + e.toString());
        }
        return bitmap;
    }


    /**
     * 生成带logo的二维码
     *
     * @param content content
     * @param logo logo
     * @return PixelMap
     */
    public PixelMap createQRCodeAddLogo(String content, PixelMap logo) {
        PixelMap qrCode = createQRCode(content);
        int qrheight = qrCode.getImageInfo().size.height;
        int qrwidth = qrCode.getImageInfo().size.width;
        int waterWidth = (int) (qrwidth * 0.2);//0.3为logo占二维码大小的倍数 建议不要过大，否则二维码失效
        float scale = waterWidth / (float) logo.getImageInfo().size.width;
        System.out.println("=======scale=" + scale);
        PixelMap waterQrcode = createWaterMaskCenter(qrCode, zoomImg(logo, scale));
//        PixelMap waterQrcode = zoomImg(logo, scale);
        return waterQrcode;

    }


    public PixelMap createQRCodeAddLogo(String content, int width, int height, PixelMap logo) {
        PixelMap qrCode = createQRCode(content, width, height);
        int qrheight = qrCode.getImageInfo().size.height;
        int qrwidth = qrCode.getImageInfo().size.width;
        int waterWidth = (int) (qrwidth * 0.3);//0.3为logo占二维码大小的倍数 建议不要过大，否则二维码失效
        float scale = waterWidth / (float) logo.getImageInfo().size.width;
        PixelMap waterQrcode = createWaterMaskCenter(qrCode, zoomImg(logo, scale));
        return waterQrcode;
    }

    /**
     * 生成条形码
     *
     * @param context context
     * @param contents contents
     * @param desiredWidth desiredWidth
     * @param desiredHeight desiredHeight
     * @return PixelMap
     */
    @Deprecated
    public PixelMap createBarcode(Context context, String contents, int desiredWidth, int desiredHeight) {
        if (TextTool.isNullOrEmpty(contents)) {
            throw new NullPointerException("contents not be null");
        }
        if (desiredWidth == 0 || desiredHeight == 0) {
            throw new NullPointerException("desiredWidth or desiredHeight not be null");
        }
        PixelMap resultBitmap;
        /**
         * 条形码的编码类型
         */
        BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;

        resultBitmap = encodeAsBitmap(contents, barcodeFormat,
                desiredWidth, desiredHeight);
        return resultBitmap;
    }

    /**
     * 生成条形码
     *
     * @param context context
     * @param contents contents
     * @param desiredWidth desiredWidth
     * @param desiredHeight desiredHeight
     * @return PixelMap
     */
    public PixelMap createBarCodeWithText(Context context, String contents, int desiredWidth,
                                          int desiredHeight) {
        return createBarCodeWithText(context, contents, desiredWidth, desiredHeight, null);
    }

    public PixelMap createBarCodeWithText(Context context, String contents, int desiredWidth,
                                          int desiredHeight, TextViewConfig config) {
        if (TextTool.isNullOrEmpty(contents)) {
            throw new NullPointerException("contents not be null");
        }
        if (desiredWidth == 0 || desiredHeight == 0) {
            throw new NullPointerException("desiredWidth or desiredHeight not be null");
        }
        PixelMap resultBitmap;

        /**
         * 条形码的编码类型
         */
        BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;

        PixelMap barcodeBitmap = encodeAsBitmap(contents, barcodeFormat,
                desiredWidth, desiredHeight);

        PixelMap codeBitmap = createCodeBitmap(contents, barcodeBitmap.getImageInfo().size.width,
                barcodeBitmap.getImageInfo().size.height, context, config);

        resultBitmap = mixtureBitmap(barcodeBitmap, codeBitmap, new Point(
                0, desiredHeight));
        return resultBitmap;
    }

    private PixelMap encodeAsBitmap(String contents, BarcodeFormat format, int desiredWidth, int desiredHeight) {
        final int WHITE = 0xFFFFFFFF;
        final int BLACK = 0xFF000000;

        MultiFormatWriter writer = new MultiFormatWriter();
        BitMatrix result = null;
        try {
            result = writer.encode(contents, format, desiredWidth,
                    desiredHeight, null);
        } catch (WriterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        int width = result.getWidth();
        int height = result.getHeight();
        int[] pixels = new int[width * height];
        // All are 0, or black, by default
        for (int y = 0; y < height; y++) {
            int offset = y * width;
            for (int x = 0; x < width; x++) {
                pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
            }
        }
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(width, height);
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        PixelMap bitmap = PixelMap.create(initializationOptions);
        bitmap.writePixels(pixels, 0, width, new Rect(0, 0, width, height));
        return bitmap;
    }


    private PixelMap createCodeBitmap(String contents, int width, int height, Context context,
                                      TextViewConfig config) {
        if (config == null) {
            config = new TextViewConfig();
        }
        Text tv = new Text(context);
        tv.setLayoutConfig(new DirectionalLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT));
        tv.setText(contents);
        tv.setTextSize(config.size == 0 ? tv.getTextSize() : (int) config.size);
        tv.setHeight(height);
        tv.setTextAlignment(config.gravity);
        tv.setMaxTextLines(config.maxLines);
        tv.setWidth(width);
        tv.setTextColor(config.color);

//        tv.estimateSize(Component.EstimateSpec.get(0, View.MeasureSpec.UNSPECIFIED),
//                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
//        tv.setLayoutConfig(new ComponentContainer.LayoutConfig(tv.getEstimatedWidth(), tv.getEstimatedHeight()));
//        tv.buildDrawingCache();
        return null;
    }

    public static class TextViewConfig {

        private int gravity = TextAlignment.CENTER;
        private int maxLines = 1;
        private Color color = Color.BLACK;
        private float size;

        public TextViewConfig() {
        }

        public void setGravity(int gravity) {
            this.gravity = gravity;
        }

        public void setMaxLines(int maxLines) {
            this.maxLines = maxLines;
        }

        public void setColor(Color color) {
            this.color = color;
        }

        public void setSize(float size) {
            this.size = size;
        }
    }

    /**
     * 将两个Bitmap合并成一个
     *
     * @param first PixelMap
     * @param second PixelMap
     * @param fromPoint 第二个PixelMap开始绘制的起始位置（相对于第一个PixelMap）
     * @return PixelMap
     */
    private PixelMap mixtureBitmap(PixelMap first, PixelMap second, Point fromPoint) {
        if (first == null || second == null || fromPoint == null) {
            return null;
        }

        int width = Math.max(first.getImageInfo().size.width, second.getImageInfo().size.width);

        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.size = new Size(width, first.getImageInfo().size.height + second.getImageInfo().size.height);
        PixelMap pixelMap = PixelMap.create(initializationOptions);// 创建一个新的和SRC长度宽度一样的位图
        Canvas cv = new Canvas(new Texture(pixelMap));
        cv.drawPixelMapHolder(new PixelMapHolder(first), 0, 0, null);
        cv.drawPixelMapHolder(new PixelMapHolder(second), fromPoint.getPointX(), fromPoint.getPointY(), null);
        cv.save();
        cv.restore();

        return pixelMap;
    }

    /**
     * 设置水印图片到中间
     *
     * @param src 二维码
     * @param watermark 水印
     * @return PixelMap
     */
    private PixelMap createWaterMaskCenter(PixelMap src, PixelMap watermark) {
        System.out.println("========createWaterMaskCenter1" + src.getImageInfo());
        System.out.println("========createWaterMaskCenter2" + watermark.getImageInfo().size.width);
        return createWaterMaskBitmap(src, watermark,
                (src.getImageInfo().size.width - watermark.getImageInfo().size.width) / 2,
                (src.getImageInfo().size.height - watermark.getImageInfo().size.height) / 2);
    }

    private PixelMap createWaterMaskBitmap(PixelMap src, PixelMap watermark, int paddingLeft, int paddingTop) {
        if (src == null) {
            return null;
        }
        int width = src.getImageInfo().size.width;
        int height = src.getImageInfo().size.height;
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.size = new Size(width, height);
        PixelMap pixelMap = PixelMap.create(initializationOptions);// 创建一个新的和SRC长度宽度一样的位图
        Canvas canvas = new Canvas(new Texture(pixelMap));
        Paint paint = new Paint();
        canvas.drawPixelMapHolder(new PixelMapHolder(src), 0, 0, paint);
        canvas.drawPixelMapHolder(new PixelMapHolder(watermark), paddingLeft, paddingTop, paint);
        canvas.save();
        canvas.restore();
        return pixelMap;
    }

    /**
     * 缩放Bitmap
     *
     * @param bm PixelMap
     * @param f float
     * @return PixelMap
     */
    private PixelMap zoomImg(PixelMap bm, float f) {

        int width = bm.getImageInfo().size.width;
        int height = bm.getImageInfo().size.height;

        float scaleWidth = f;
        float scaleHeight = f;

        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size((int) (width * f), (int) (height * f));
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        PixelMap pixelMap = PixelMap.create(bm, initializationOptions);
        return pixelMap;
    }


    /**
     * Return the width of screen, in pixel.
     * @param mContext  Context
     * @return the width of screen, in pixel
     */
    public int getScreenWidth(Context mContext) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(mContext).get();
        Point point = new Point();
        display.getSize(point);
        return (int) point.getPointX();
    }

    /**
     * Return the height of screen, in pixel.
     * @param  mContext  Context
     * @return the height of screen, in pixel
     */
    public int getScreenHeight(Context mContext) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(mContext).get();
        Point point = new Point();
        display.getSize(point);
        return (int) point.getPointY();
    }

    /**
     * 返回当前屏幕是否为竖屏。
     *
     * @param  context  Context
     * @return 当且仅当当前屏幕为竖屏时返回true, 否则返回false。
     */
    public boolean isScreenOriatationPortrait(Context context) {
        return context.getResourceManager().getConfiguration().direction == Configuration.DIRECTION_VERTICAL;
    }

    public float getFingerSpacing(TouchEvent touchEvent) {
        MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
//        float x = event.getX(0) - event.getX(1);
//        float y = event.getY(0) - event.getY(1);
        float x = point.getX();
        float y = point.getY();
        return (float) Math.sqrt(x * x + y * y);
    }


    /**
     * 对bitmap进行灰度处理
     *
     * @param bmpOriginal bmpOriginal
     * @return PixelMap
     */
    private PixelMap toGrayscale(PixelMap bmpOriginal) {
        int width, height;
        height = bmpOriginal.getImageInfo().size.height;
        width = bmpOriginal.getImageInfo().size.width;
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(width, height);
        initializationOptions.pixelFormat = PixelFormat.RGB_565;
        PixelMap pixelMap = PixelMap.create(initializationOptions);
        Canvas c = new Canvas(new Texture(pixelMap));
        Paint paint = new Paint();
        c.drawPixelMapHolder(new PixelMapHolder(bmpOriginal), 0, 0, paint);
        return pixelMap;
    }

    /**
     * 压缩图片
     *
     * @param path path
     * @return PixelMap
     */
    private PixelMap compressImage(String path) {
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        ImageSource imageSource = ImageSource.create(path, sourceOptions);
        int sampleSizeH = (int) (imageSource.getImageInfo().size.height / (float) 800);
        int sampleSizeW = (int) (imageSource.getImageInfo().size.width / (float) 800);
        int sampleSize = Math.max(sampleSizeH, sampleSizeW);
        if (sampleSize <= 0) {
            sampleSize = 1;
        }
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        decodingOptions.sampleSize = sampleSize;
        decodingOptions.desiredPixelFormat = PixelFormat.RGB_565;
        PixelMap pixelmap = imageSource.createPixelmap(decodingOptions);
        return pixelmap;
    }


    public boolean deleteTempFile(String delFile) {
        File file = new File(delFile);
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    //震动提醒
    public void getVibrator() {
        VibratorAgent vibratorAgent = new VibratorAgent();
        // 查询硬件设备上的振动器列表
        List<Integer> vibratorList = vibratorAgent.getVibratorIdList();
        if (vibratorList.isEmpty()) {
            return;
        }
        int vibratorId = vibratorList.get(0);
//        List<Integer> vibratorIdList = vibratorAgent.getVibratorIdList();
        int[] pattern = {0, 50, 0, 0};
        vibratorAgent.start(vibratorId, VibrationPattern.createPeriod(pattern, 1));
    }

    private static byte[] yuvs;

    /**
     * YUV420sp
     *
     * @param inputWidth inputWidth
     * @param inputHeight inputHeight
     * @param scaled scaled
     * @return byte[]
     */
    public static byte[] getYUV420sp(int inputWidth, int inputHeight, PixelMap scaled) {
        int[] argb = new int[inputWidth * inputHeight];
        scaled.readPixels(argb, 0, inputWidth, new Rect(0, 0, inputWidth, inputHeight));
        int requiredWidth = inputWidth % 2 == 0 ? inputWidth : inputWidth + 1;
        int requiredHeight = inputHeight % 2 == 0 ? inputHeight : inputHeight + 1;

        int byteLength = requiredWidth * requiredHeight * 3 / 2;
        if (yuvs == null || yuvs.length < byteLength) {
            yuvs = new byte[byteLength];
        } else {
            Arrays.fill(yuvs, (byte) 0);
        }
        encodeYUV420SP(yuvs, argb, inputWidth, inputHeight);
        scaled.release();
        return yuvs;
    }

    /**
     * RGB TO YUV420sp
     *
     * @param yuv420sp inputWidth * inputHeight * 3 / 2
     * @param argb     inputWidth * inputHeight
     * @param width width
     * @param height height
     */
    private static void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
        final int frameSize = width * height;
        int Y, U, V;
        int yIndex = 0;
        int uvIndex = frameSize;

        // int a, R, G, B;
        int R, G, B;
        //
        int argbIndex = 0;
        //

        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {

                // a is not used obviously
                // a = (argb[argbIndex] & 0xff000000) >> 24;
                R = (argb[argbIndex] & 0xff0000) >> 16;
                G = (argb[argbIndex] & 0xff00) >> 8;
                B = (argb[argbIndex] & 0xff);
                //
                argbIndex++;

                // well known RGB to YUV algorithm
                Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
                U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
                V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;

                //
                Y = Math.max(0, Math.min(Y, 255));
                U = Math.max(0, Math.min(U, 255));
                V = Math.max(0, Math.min(V, 255));

                // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
                // meaning for every 4 Y pixels there are 1 V and 1 U. Note the sampling is every other
                // pixel AND every other scanline.
                // ---Y---
                yuv420sp[yIndex++] = (byte) Y;
                // ---UV---
                if ((j % 2 == 0) && (i % 2 == 0)) {
                    //
                    yuv420sp[uvIndex++] = (byte) V;
                    //
                    yuv420sp[uvIndex++] = (byte) U;
                }
            }
        }
    }

    public static int calculateInSampleSize(ImageSource.DecodingOptions options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.desiredSize.height;
        final int width = options.desiredSize.width;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public static PixelMap decodeSampledBitmapFromFile(String imgPath, int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
        options.allowPartialImage = true;
        ImageSource imageSource = ImageSource.create(imgPath, null);
        imageSource.createPixelmap(options);
        // Calculate inSampleSize
        options.sampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // Decode bitmap with inSampleSize set
        options.allowPartialImage = false;
        PixelMap pixelmap = imageSource.createPixelmap(options);
        return pixelmap;
    }


    /**
     * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, reuse the same reader
     * objects from one decode to the next.
     *
     * @param data byte[]
     * @param width width
     * @param height height
     * @return  Result
     */
    public static Result decodeImage(byte[] data, int width, int height) {
        Result result = null;
        try {
            Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
            PlanarYUVLuminanceSource source =
                    new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);

            BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
            // BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
            QRCodeReader reader2 = new QRCodeReader();
            result = reader2.decode(bitmap1, hints);
        } catch (ReaderException e) {
        }
        return result;
    }

    public static void saveImage(Context context, String fileName, PixelMap pixelMap) {
        try {
            ValuesBucket valuesBucket = new ValuesBucket();
            valuesBucket.putString(AVStorage.Images.Media.DISPLAY_NAME, fileName);
            valuesBucket.putString("relative_path", "DCIM/");
            valuesBucket.putString(AVStorage.Images.Media.MIME_TYPE, "image/JPEG");
            //应用独占
            valuesBucket.putInteger("is_pending", 1);
            DataAbilityHelper helper = DataAbilityHelper.creator(context);
            int id = helper.insert(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, valuesBucket);
            Uri uri = Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, String.valueOf(id));
            //这里需要"w"写权限
            FileDescriptor fd = helper.openFile(uri, "w");
            ImagePacker imagePacker = ImagePacker.create();
            ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
            OutputStream outputStream = new FileOutputStream(fd);
            packingOptions.format = "image/jpeg";
            packingOptions.quality = 90;
            boolean result = imagePacker.initializePacking(outputStream, packingOptions);
            if (result) {
                result = imagePacker.addImage(pixelMap);
                if (result) {
                    long dataSize = imagePacker.finalizePacking();
                }
            }
            outputStream.flush();
            outputStream.close();
            valuesBucket.clear();
            //解除独占
            valuesBucket.putInteger("is_pending", 0);
            helper.update(uri, valuesBucket, null);
        } catch (Exception e) {
            System.out.println("======saveImage="+e.getMessage());
        }
    }
    /**
     * 转成图片
     * @param context c
     * @param mResource m
     * @return PixelMap
     * @throws IOException ex
     * @throws NotExistException ex
     */
    public static PixelMap getPixelmap(Context context, int mResource) throws IOException, NotExistException {
        ResourceManager rsrc = context.getResourceManager();
        if (rsrc == null) {
            return null;
        }
        Resource resource = null;
        if (mResource != 0) {
            resource = rsrc.getResource(mResource);
        }
        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
        ImageSource imageSource = null;
        try {
            imageSource = ImageSource.create(readResource(resource), srcOpts);
        } finally {
            close(resource);
        }
        if (imageSource == null) {
            throw new FileNotFoundException();
        }
        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        decodingOpts.desiredSize = new Size(0, 0);
        decodingOpts.desiredRegion = new ohos.media.image.common.Rect(0, 0, 0, 0);
        decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;

        PixelMap pixelmap = imageSource.createPixelmap(decodingOpts);
        return pixelmap;
    }

    private static byte[] readResource(Resource resource) {
        final int bufferSize = 1024;
        final int ioEnd = -1;

        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[bufferSize];
        while (true) {
            try {
                int readLen = resource.read(buffer, 0, bufferSize);
                if (readLen == ioEnd) {
                    break;
                }
                output.write(buffer, 0, readLen);
            } catch (IOException e) {
                Log.error(e.getMessage());
                break;
            } finally {
                try {
                    output.close();
                } catch (IOException e) {
                    Log.error(e.getMessage());
                }
            }
        }
        return output.toByteArray();
    }

    private static void close(Resource resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                Log.error(e.getMessage());
            }
        }
    }

    /**
     * 获取颜色
     * @param context 上下文
     * @param id id
     * @return 颜色
     */
    public static int getColor(Context context, int id) {
        int result = 0;
        if (context == null) {
            return result;
        }
        ResourceManager manager = context.getResourceManager();
        if (manager == null) {
            return result;
        }
        try {
            result = manager.getElement(id).getColor();
        } catch (IOException | WrongTypeException | NotExistException e) {
            Log.error(e.getMessage());
        }
        return result;
    }
}
